/*
 * Copyright 2012 XueSong Guo.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.webwheel.setters;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

public class JSonSetter extends AbstractSetter<Object> {

    private int flag;//0: bean 1:array 2:list
    private JavaType type;
    private Class componentType;

    public static ObjectMapper objectMapper = new ObjectMapper();

    public JSonSetter(Type javaType) {
        if (javaType instanceof ParameterizedType) {
            ParameterizedType pt = (ParameterizedType) javaType;
            if (pt.getRawType() == List.class) {
                type = objectMapper.getTypeFactory().constructType(pt.getActualTypeArguments()[0]);
                flag = 2;
            }
        }
        if (type == null) {
            if (javaType instanceof Class) {
                Class t = (Class) javaType;
                if (t.isArray()) {
                    type = objectMapper.getTypeFactory().constructType(componentType = t.getComponentType());
                    flag = 1;
                }
            }
        }
        if (type == null) {
            type = objectMapper.getTypeFactory().constructType(javaType);
        }
    }

    @Override
    protected Object get(Object param) {
        if (!(param instanceof String[])) return null;
        String[] ss = (String[]) param;
        try {
            switch (flag) {
                case 2: {
                    List<Object> list = new ArrayList<Object>();
                    for (String s : ss) {
                        list.add(objectMapper.readValue(s, type));
                    }
                    return list;
                }
                case 1: {
                    Object list = Array.newInstance(componentType, ss.length);
                    for (int i = 0; i < ss.length; i++) {
                        Array.set(list, i, objectMapper.readValue(ss[i], type));
                    }
                    return list;
                }
                default: {
                    String s = ss[0];
                    return objectMapper.readValue(s, type);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
